package com.ssm.aop;

import com.ssm.util.LogHelper;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import jakarta.servlet.http.HttpServletRequest;
import java.util.Arrays;

/**
 * 日志切面类
 * 【Spring: AOP应用】
 * 使用AOP实现日志记录，对控制器方法进行环绕通知，记录请求信息和执行时间
 */
@Aspect
@Component
public class LogAspect {

    @Autowired
    private LogHelper logHelper;

    /**
     * 定义切点，拦截controller包下的所有方法
     * 【Spring: AOP切点定义】
     */
    @Pointcut("execution(* com.ssm.controller.*.*(..))")
    public void controllerPointcut() {}

    /**
     * 前置通知：在方法执行前执行
     * 【Spring: AOP前置通知】
     */
    @Before("controllerPointcut()")
    public void doBefore(JoinPoint joinPoint) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        
        // 记录请求信息
        logHelper.info("==========请求开始==========");
        logHelper.info("请求URL: " + request.getRequestURL().toString());
        logHelper.info("请求方法: " + request.getMethod());
        logHelper.info("请求IP: " + request.getRemoteAddr());
        logHelper.info("请求类方法: " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
        logHelper.info("请求参数: " + Arrays.toString(joinPoint.getArgs()));
    }

    /**
     * 环绕通知：在方法执行前后执行
     * 【Spring: AOP环绕通知】
     */
    @Around("controllerPointcut()")
    public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        Object result = proceedingJoinPoint.proceed();
        long endTime = System.currentTimeMillis();
        logHelper.info("方法执行时间: " + (endTime - startTime) + "ms");
        return result;
    }

    /**
     * 后置通知：在方法执行后执行
     * 【Spring: AOP后置通知】
     */
    @AfterReturning(pointcut = "controllerPointcut()", returning = "result")
    public void doAfterReturning(Object result) {
        logHelper.info("返回结果: " + result);
        logHelper.info("==========请求结束==========");
    }

    /**
     * 异常通知：在方法抛出异常时执行
     * 【Spring: AOP异常通知】
     */
    @AfterThrowing(pointcut = "controllerPointcut()", throwing = "e")
    public void doAfterThrowing(Exception e) {
        logHelper.error("发生异常: " + e.getMessage());
    }
} 